package comunications;

import gameState.Player;
import gameState.Ring;

import java.io.Serializable;
import java.net.InetAddress;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

import businessLogic.PlayerActions;
import crashManager.CrashManager;
import crashManager.DeathList;
import gameState.Table;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;

public class ClientComunicateImpl extends UnicastRemoteObject implements Remote, Serializable, ClientComunicateInterface{
	
	private static final long serialVersionUID = 1L;
	private Player nextPlayer;
	private PlayerActions me;
	private Ring ring = Ring.getInstance();
    private DeathList deathList = DeathList.getInstance();
    Logger logger = Logger.getLogger(this.getClass().getSimpleName());
//    SimpleFormatter sf = new SimpleFormatter();
//
//    sf.format("non ci siamo proprio");
//	
	
	
	protected ClientComunicateImpl() throws RemoteException {
		super();
	}


	public void creaPlayerActions(){
		try {
			String myIP = InetAddress.getLocalHost().getHostAddress();
			for(int i=0; i<ring.size(); i++){
				if(ring.getPlayer(i).getIp().equals(myIP)){
					logger.info("[ClientComunicateImpl || creaPlayerActions()] creo PlayerActions");
					me = new PlayerActions(ring.getPlayer(i));
                    ring.setMe(ring.getPlayer(i));
                    me.runGraphic();
                    me.startPing();
				}
			}
		}
		catch(Exception e){e.printStackTrace();}
	}


	public void bringTable(Table t) throws RemoteException{
            try{
                int myVers = me.getTable().getVersion();
                int newVers = t.getVersion();
                logger.fine("[ClientComunicateImpl || bringTable] myVers="+myVers+" e newVers="+newVers);
                if(newVers==-2){
                    me.iAmLegend();
                }
                else if((myVers == newVers) && !(me.isTheFirstMatch(t)) && !(me.isMyTurnToDeal())){
                    logger.info("[ClientComunicateImpl || bringTable] chiamo sameVersionManager");
                    boolean mustSendTable = me.sameVersionManager();

                    logger.fine("[ClientComunicateImpl || bringTable()] risultato di sameVersionManager "+ mustSendTable);
                    //TODO by kika ....
                    if(mustSendTable){
                        logger.fine("[ClientComunicateImpl || bringTable()] tento di inviare il tavolo vers. "+me.getTable().getVersion()+" al player"+ring.getMyNextPlayer().getName());
                    	Thread st = new SendTable(me.getTable(), ring.getMyNextPlayer());
                    	st.start();
                        logger.fine("[ClientComunicateImpl || bringTable()] ho inviato il tavolo vers. "+me.getTable().getVersion()+" al player"+ring.getMyNextPlayer().getName());
                    }
                }
                else if((newVers == -1) || (newVers == 0) || (newVers > myVers)){
                    logger.info("[ClientComunicateImpl || bringTable] chiamo manageTable");
                    me.manageTable(t);

                    //invece di fare SendTable di t lo faccio di me.getTable()
                    logger.fine("[ClientComunicateImpl || bringTable] il tavolo che sto per inviare ha versione "+me.getTable().getVersion());
                    Thread st = new SendTable(me.getTable(), ring.getMyNextPlayer());
                    st.sleep(100);
                    st.start();
                }
            }
            catch(Exception e){e.printStackTrace();}
        }


   	public void bringFirstTable(Table t) throws RemoteException{
            Table myTable = Table.getInstance();
            myTable.setPlayers(t.getPlayers());
            myTable.setVersion(t.getVersion());
            myTable.setScore(t.getScore());
            myTable.setDealerList(t.getDealerList());
            myTable.setHasLaid(t.getHasLaid());
            myTable.setHeel(t.getHeel());
            myTable.setWell(t.getWell());
            myTable.setWinner(t.getWinner());
            myTable.setCurrentPlayer(t.getCurrentPlayer());
            logger.fine("[ClientComunicateImpl || bringFirstTable] currentPlayer "+myTable.getCurrentPlayer());
            logger.fine("[ClientComunicateImpl || bringFirstTable] vers:"+t.getVersion());
        }


        public void bringRing(Ring r) throws RemoteException{
            Ring ring = Ring.getInstance();
            ring.addEntireRing(r);
            logger.info("[ClientCommunicateImpl || bringRing] Ring appena ricevuto:");
            ring.stampaRing();
        }

        public String quiParloIo() throws RemoteException{
            return "qui parla "+me.getName();
        }


        public void tryToStartGame(){
            me.startGame();
        }


        public boolean areYouALive(){
            return true;
        }

        public int areYouALive(int numero){
            return numero;
        }


        public void receiveDeathNotification(Player deathPlayer){
            logger.info("[ClientComunicateImpl || receiveDeathNotification] ricevuta deatNotification riguardo "+deathPlayer.getName());
            if(ring.existPlayerInTheRing(deathPlayer)){
                ring.removePlayer(deathPlayer);
                if(ring.amIalone()){
                    me.iAmLegend();
                }
                logger.info("[ClientComunicateImpl || receiveDeathNotification] avevo "+deathPlayer.getName()+" nel mio ring e l'ho rimosso");

                try{
                    deathList.addDeathPlayer(deathPlayer);
                    Thread sdn = new SendDeathNotification();
                    sdn.start();
                }

                catch(Exception e){
                    e.printStackTrace();
                    CrashManager cm = new CrashManager();
                    cm.solveNext();
                }
            }
            else{
                if(deathList.containPlayer(deathPlayer)){
                    deathList.removeDeathPlayer(deathPlayer);
                }
            }
        }
}
